{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {
        "pycharm": {}
      },
      "outputs": [],
      "source": [
        "import numpy as np\n",
        "import pandas as pd"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "pycharm": {}
      },
      "source": [
        "### 读取原商品"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {
        "pycharm": {}
      },
      "outputs": [
        {
          "data": {
            "text/html": [
              "\u003cdiv\u003e\n",
              "\u003cstyle scoped\u003e\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "\u003c/style\u003e\n",
              "\u003ctable border\u003d\"1\" class\u003d\"dataframe\"\u003e\n",
              "  \u003cthead\u003e\n",
              "    \u003ctr style\u003d\"text-align: right;\"\u003e\n",
              "      \u003cth\u003e\u003c/th\u003e\n",
              "      \u003cth\u003emovie_id\u003c/th\u003e\n",
              "      \u003cth\u003egenres\u003c/th\u003e\n",
              "    \u003c/tr\u003e\n",
              "  \u003c/thead\u003e\n",
              "  \u003ctbody\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e0\u003c/th\u003e\n",
              "      \u003ctd\u003e4\u003c/td\u003e\n",
              "      \u003ctd\u003eComedy|Drama|Romance\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e1\u003c/th\u003e\n",
              "      \u003ctd\u003e8\u003c/td\u003e\n",
              "      \u003ctd\u003eAdventure|Children\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e2\u003c/th\u003e\n",
              "      \u003ctd\u003e9\u003c/td\u003e\n",
              "      \u003ctd\u003eAction\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e3\u003c/th\u003e\n",
              "      \u003ctd\u003e12\u003c/td\u003e\n",
              "      \u003ctd\u003eComedy|Horror\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e4\u003c/th\u003e\n",
              "      \u003ctd\u003e13\u003c/td\u003e\n",
              "      \u003ctd\u003eAdventure|Animation|Children\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "  \u003c/tbody\u003e\n",
              "\u003c/table\u003e\n",
              "\u003c/div\u003e"
            ],
            "text/plain": [
              "   movie_id                        genres\n",
              "0         4          Comedy|Drama|Romance\n",
              "1         8            Adventure|Children\n",
              "2         9                        Action\n",
              "3        12                 Comedy|Horror\n",
              "4        13  Adventure|Animation|Children"
            ]
          },
          "execution_count": 3,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# 不需要用到title所以取第一列和第三列\n",
        "df_movie_old \u003d pd.read_csv(\u0027./data/movie_old.csv\u0027,usecols\u003d[0,2])\n",
        "df_movie_old.head()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "pycharm": {}
      },
      "source": [
        "### 统计原物品中所有的特征"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {
        "pycharm": {}
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "[\u0027Crime\u0027,\n",
              " \u0027War\u0027,\n",
              " \u0027Action\u0027,\n",
              " \u0027Animation\u0027,\n",
              " \u0027Documentary\u0027,\n",
              " \u0027Comedy\u0027,\n",
              " \u0027Adventure\u0027,\n",
              " \u0027Fantasy\u0027,\n",
              " \u0027Thriller\u0027,\n",
              " \u0027Musical\u0027,\n",
              " \u0027Western\u0027,\n",
              " \u0027Horror\u0027,\n",
              " \u0027Drama\u0027,\n",
              " \u0027Sci-Fi\u0027,\n",
              " \u0027IMAX\u0027,\n",
              " \u0027Romance\u0027,\n",
              " \u0027Children\u0027,\n",
              " \u0027Film-Noir\u0027,\n",
              " \u0027Mystery\u0027]"
            ]
          },
          "execution_count": 6,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": "total_genres \u003d set()\n# 遍历所有的genres\nfor genres in df_movie_old[\u0027genres\u0027]:\n    # |\u003d取并集\n    total_genres |\u003d set(genres.split(\u0027|\u0027))\n\ntotal_genres \u003d list(total_genres)\ntotal_genres"
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "pycharm": {}
      },
      "source": [
        "### 读取新物品"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "metadata": {
        "pycharm": {}
      },
      "outputs": [
        {
          "data": {
            "text/html": [
              "\u003cdiv\u003e\n",
              "\u003cstyle scoped\u003e\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "\u003c/style\u003e\n",
              "\u003ctable border\u003d\"1\" class\u003d\"dataframe\"\u003e\n",
              "  \u003cthead\u003e\n",
              "    \u003ctr style\u003d\"text-align: right;\"\u003e\n",
              "      \u003cth\u003e\u003c/th\u003e\n",
              "      \u003cth\u003emovie_id\u003c/th\u003e\n",
              "      \u003cth\u003egenres\u003c/th\u003e\n",
              "    \u003c/tr\u003e\n",
              "  \u003c/thead\u003e\n",
              "  \u003ctbody\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e0\u003c/th\u003e\n",
              "      \u003ctd\u003e14\u003c/td\u003e\n",
              "      \u003ctd\u003eDrama\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e1\u003c/th\u003e\n",
              "      \u003ctd\u003e18\u003c/td\u003e\n",
              "      \u003ctd\u003eComedy\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e2\u003c/th\u003e\n",
              "      \u003ctd\u003e30\u003c/td\u003e\n",
              "      \u003ctd\u003eCrime|Drama\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e3\u003c/th\u003e\n",
              "      \u003ctd\u003e35\u003c/td\u003e\n",
              "      \u003ctd\u003eDrama|Romance\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e4\u003c/th\u003e\n",
              "      \u003ctd\u003e41\u003c/td\u003e\n",
              "      \u003ctd\u003eDrama|War\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "  \u003c/tbody\u003e\n",
              "\u003c/table\u003e\n",
              "\u003c/div\u003e"
            ],
            "text/plain": [
              "   movie_id         genres\n",
              "0        14          Drama\n",
              "1        18         Comedy\n",
              "2        30    Crime|Drama\n",
              "3        35  Drama|Romance\n",
              "4        41      Drama|War"
            ]
          },
          "execution_count": 8,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "df_movie_new \u003d pd.read_csv(\u0027./data/movie_new.csv\u0027,usecols\u003d[0,2])\n",
        "df_movie_new.head()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "pycharm": {}
      },
      "source": [
        "### 建立原物品和新物品的特征矩阵"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "metadata": {
        "pycharm": {}
      },
      "outputs": [],
      "source": [
        "# 原物品id--\u003eindex\n",
        "movie_old_id_to_index_dict \u003d {}\n",
        "\n",
        "# 新物品id--\u003eindex\n",
        "movie_new_id_to_index_dict \u003d {}\n",
        "\n",
        "# 初始化原物品和新物品的特征矩阵\n",
        "movie_old_genres_array \u003d np.zeros(\n",
        "    shape\u003d(len(df_movie_old),len(total_genres))\n",
        ")\n",
        "movie_new_genres_array \u003d np.zeros(\n",
        "    shape\u003d(len(df_movie_new),len(total_genres))\n",
        ")\n",
        "\n",
        "# index物理索引\n",
        "# 老物品\n",
        "for index in range(len(df_movie_old)):\n",
        "    movie_id \u003d df_movie_old.iloc[index][\u0027movie_id\u0027]\n",
        "    movie_old_id_to_index_dict[movie_id] \u003d index\n",
        "    genres \u003d df_movie_old.iloc[index][\u0027genres\u0027].split(\u0027|\u0027)\n",
        "    \n",
        "    # 创建特征行向量\n",
        "    line_data \u003d np.zeros(shape\u003dlen(total_genres))\n",
        "    for i in range(len(total_genres)):\n",
        "        if total_genres[i] in genres:\n",
        "            line_data[i] \u003d 1\n",
        "\n",
        "    # 赋值给index行\n",
        "    movie_old_genres_array[index] \u003d line_data\n",
        "\n",
        "# 新物品\n",
        "for index in range(len(df_movie_new)):\n",
        "    movie_id \u003d df_movie_new.iloc[index][\u0027movie_id\u0027]\n",
        "    movie_new_id_to_index_dict[movie_id] \u003d index\n",
        "    genres \u003d df_movie_new.iloc[index][\u0027genres\u0027].split(\u0027|\u0027)\n",
        "    \n",
        "    # 创建特征行向量\n",
        "    line_data \u003d np.zeros(shape\u003dlen(total_genres))\n",
        "    for i in range(len(total_genres)):\n",
        "        if total_genres[i] in genres:\n",
        "            line_data[i] \u003d 1\n",
        "    # 赋值给index行\n",
        "    movie_new_genres_array[index] \u003d line_data\n",
        "    "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "pycharm": {}
      },
      "source": [
        "### 原物品到新物品的相似度矩阵"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "metadata": {
        "pycharm": {}
      },
      "outputs": [],
      "source": [
        "# 相当于公式分母中的平方加和\n",
        "movie_old_genres_column_sum_array \u003d np.sum(movie_old_genres_array,axis\u003d1)\n",
        "movie_new_genres_column_sum_array \u003d np.sum(movie_new_genres_array,axis\u003d1)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "metadata": {
        "pycharm": {}
      },
      "outputs": [],
      "source": [
        "# 初始化相似度矩阵\n",
        "movie_sim_array \u003d np.zeros(\n",
        "    shape\u003d(len(df_movie_old),len(df_movie_new))\n",
        ")\n",
        "\n",
        "# 计算相似度\n",
        "for index in range(len(df_movie_old)):\n",
        "    v1 \u003d np.dot(\n",
        "        movie_old_genres_array[index],movie_new_genres_array.T\n",
        "    )\n",
        "    # 保留三位有效数字\n",
        "    v2 \u003d np.around(np.sqrt(\n",
        "        movie_old_genres_column_sum_array[index] * movie_new_genres_column_sum_array),3)\n",
        "    # 计算出相似度结果，保留两位有效数字\n",
        "    movie_sim_array[index] \u003d np.around(v1 / v2,2)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "metadata": {
        "pycharm": {}
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "array([[0.58, 0.58, 0.41, ..., 0.41, 0.58, 0.  ],\n",
              "       [0.  , 0.  , 0.  , ..., 0.  , 0.  , 0.  ],\n",
              "       [0.  , 0.  , 0.  , ..., 0.71, 0.  , 0.  ],\n",
              "       ...,\n",
              "       [0.71, 0.  , 0.5 , ..., 0.5 , 0.71, 0.  ],\n",
              "       [0.  , 0.  , 0.  , ..., 0.41, 0.  , 0.58],\n",
              "       [0.71, 0.  , 0.5 , ..., 0.5 , 0.71, 0.  ]])"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "movie_sim_array"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "pycharm": {}
      },
      "source": [
        "### 导入原物品的打分"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "metadata": {
        "pycharm": {}
      },
      "outputs": [
        {
          "data": {
            "text/html": [
              "\u003cdiv\u003e\n",
              "\u003cstyle scoped\u003e\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "\u003c/style\u003e\n",
              "\u003ctable border\u003d\"1\" class\u003d\"dataframe\"\u003e\n",
              "  \u003cthead\u003e\n",
              "    \u003ctr style\u003d\"text-align: right;\"\u003e\n",
              "      \u003cth\u003e\u003c/th\u003e\n",
              "      \u003cth\u003euser_id\u003c/th\u003e\n",
              "      \u003cth\u003emovie_id\u003c/th\u003e\n",
              "      \u003cth\u003erating\u003c/th\u003e\n",
              "    \u003c/tr\u003e\n",
              "  \u003c/thead\u003e\n",
              "  \u003ctbody\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e0\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e1009\u003c/td\u003e\n",
              "      \u003ctd\u003e3.5\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e1\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e1243\u003c/td\u003e\n",
              "      \u003ctd\u003e3.0\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e2\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e1848\u003c/td\u003e\n",
              "      \u003ctd\u003e3.5\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e3\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e1920\u003c/td\u003e\n",
              "      \u003ctd\u003e3.5\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e4\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e2118\u003c/td\u003e\n",
              "      \u003ctd\u003e4.0\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "  \u003c/tbody\u003e\n",
              "\u003c/table\u003e\n",
              "\u003c/div\u003e"
            ],
            "text/plain": [
              "   user_id  movie_id  rating\n",
              "0        1      1009     3.5\n",
              "1        1      1243     3.0\n",
              "2        1      1848     3.5\n",
              "3        1      1920     3.5\n",
              "4        1      2118     4.0"
            ]
          },
          "execution_count": 18,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "df_rating_old \u003d pd.read_csv(\u0027./data/rating_old.csv\u0027)\n",
        "df_rating_old.head()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "pycharm": {}
      },
      "source": [
        "### 变更id为index"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "metadata": {
        "pycharm": {}
      },
      "outputs": [
        {
          "data": {
            "text/html": [
              "\u003cdiv\u003e\n",
              "\u003cstyle scoped\u003e\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "\u003c/style\u003e\n",
              "\u003ctable border\u003d\"1\" class\u003d\"dataframe\"\u003e\n",
              "  \u003cthead\u003e\n",
              "    \u003ctr style\u003d\"text-align: right;\"\u003e\n",
              "      \u003cth\u003e\u003c/th\u003e\n",
              "      \u003cth\u003euser_id\u003c/th\u003e\n",
              "      \u003cth\u003emovie_id\u003c/th\u003e\n",
              "      \u003cth\u003erating\u003c/th\u003e\n",
              "    \u003c/tr\u003e\n",
              "  \u003c/thead\u003e\n",
              "  \u003ctbody\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e0\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e319\u003c/td\u003e\n",
              "      \u003ctd\u003e3.5\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e1\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e370\u003c/td\u003e\n",
              "      \u003ctd\u003e3.0\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e2\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e518\u003c/td\u003e\n",
              "      \u003ctd\u003e3.5\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e3\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e538\u003c/td\u003e\n",
              "      \u003ctd\u003e3.5\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e4\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e623\u003c/td\u003e\n",
              "      \u003ctd\u003e4.0\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "  \u003c/tbody\u003e\n",
              "\u003c/table\u003e\n",
              "\u003c/div\u003e"
            ],
            "text/plain": [
              "   user_id  movie_id  rating\n",
              "0        1       319     3.5\n",
              "1        1       370     3.0\n",
              "2        1       518     3.5\n",
              "3        1       538     3.5\n",
              "4        1       623     4.0"
            ]
          },
          "execution_count": 19,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "df_rating_old[\u0027movie_id\u0027] \u003d df_rating_old[\u0027movie_id\u0027].apply(lambda movie_id : movie_old_id_to_index_dict[movie_id])\n",
        "df_rating_old.head()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "metadata": {
        "pycharm": {}
      },
      "outputs": [],
      "source": [
        "# 修改列名\n",
        "df_rating_old.columns \u003d [\u0027user_id\u0027,\u0027movie_index\u0027,\u0027rating\u0027]"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "pycharm": {}
      },
      "source": [
        "### 根据用户喜欢的原物品，生成新物品的推荐"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 21,
      "metadata": {
        "pycharm": {}
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "0..100..200..300..400..500..600..700..800..900..1000..1100..1200..1300..1400..1500..1600..1700..1800..1900..2000..2100..2200..2300..2400..2500..2600..2700..2800..2900..3000..3100..3200..3300..3400..3500..3600..3700..3800..3900..4000..4100..4200..4300..4400..4500..4600..4700..4800..4900..5000..5100..5200..5300..5400..5500..5600..5700..5800..5900..6000..6100..6200..6300..6400..6500..6600..6700..6800..6900..7000..7100..7200..7300..7400..7500..7600..7700..7800..7900..8000..8100..8200..8300..8400..8500..8600..8700..8800..8900..9000..9100..9200..9300..9400..9500..9600..9700..9800..9900..10000..10100..10200..10300..10400..10500..10600..10700..10800..10900..11000..11100..11200..11300..11400..11500..11600..11700..11800..11900..12000..12100..12200..12300..12400..12500..12600..12700..12800..12900..13000..13100..13200..13300..13400..13500..13600..13700..13800..13900..14000..14100..14200..14300..14400..14500..14600..14700..14800..14900..15000..15100..15200..15300..15400..15500..15600..15700..15800..15900..16000..16100..16200..16300..16400..16500..16600..16700..16800..16900..17000..17100..17200..17300..17400..17500..17600..17700..17800..17900..18000..18100..18200..18300..18400..18500..18600..18700..18800..18900..19000..19100..19200..19300..19400..19500..19600..19700..19800..19900..20000..20100..20200..20300..20400..20500..20600..20700..20800..20900..21000..21100..21200..21300..21400..21500..21600..21700..21800..21900..22000..22100..22200..22300..22400..22500..22600..22700..22800..22900..23000..23100..23200..23300..23400..23500..23600..23700..23800..23900..24000..24100..24200..24300..24400..24500..24600..24700..24800..24900..25000..25100..25200..25300..25400..25500..25600..25700..25800..25900..26000..26100..26200..26300..26400..26500..26600..26700..26800..26900..27000..27100..27200..27300..27400..27500..27600..27700..27800..27900..28000..28100..28200..28300..28400..28500..28600..28700..28800..28900..29000..29100..29200..29300..29400..29500..29600..29700..29800..29900..30000..30100..30200..30300..30400..30500..30600.."
          ]
        }
      ],
      "source": [
        "# 评分大于等于4分记为喜欢\n",
        "user_recommend \u003d {}\n",
        "\n",
        "for index,(user_id,groupby_userid) in enumerate(df_rating_old.groupby(\u0027user_id\u0027)):\n",
        "    movies_rating \u003d groupby_userid.groupby(\u0027movie_index\u0027)[\u0027rating\u0027].mean().sort_values(ascending\u003dFalse)\n",
        "    \n",
        "    # 找到用户喜欢的原有的物品的索引\n",
        "    user_fav \u003d movies_rating[\n",
        "        movies_rating \u003e\u003d 4\n",
        "    ].index.tolist()\n",
        "    \n",
        "    # 找到相似度高的对应的新物品\n",
        "    user_recommend[user_id] \u003d set(np.where(\n",
        "        movie_sim_array[user_fav] \u003e\u003d 0.85)[1].tolist()[:100])\n",
        "    if index % 100 \u003d\u003d 0:print(index,end\u003d\u0027..\u0027)\n",
        "        "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "pycharm": {}
      },
      "source": [
        "### 读物用户对新物品的实际打分"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "metadata": {
        "pycharm": {}
      },
      "outputs": [
        {
          "data": {
            "text/html": [
              "\u003cdiv\u003e\n",
              "\u003cstyle scoped\u003e\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "\u003c/style\u003e\n",
              "\u003ctable border\u003d\"1\" class\u003d\"dataframe\"\u003e\n",
              "  \u003cthead\u003e\n",
              "    \u003ctr style\u003d\"text-align: right;\"\u003e\n",
              "      \u003cth\u003e\u003c/th\u003e\n",
              "      \u003cth\u003euser_id\u003c/th\u003e\n",
              "      \u003cth\u003emovie_id\u003c/th\u003e\n",
              "      \u003cth\u003erating\u003c/th\u003e\n",
              "    \u003c/tr\u003e\n",
              "  \u003c/thead\u003e\n",
              "  \u003ctbody\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e0\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e1217\u003c/td\u003e\n",
              "      \u003ctd\u003e3.5\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e1\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e1348\u003c/td\u003e\n",
              "      \u003ctd\u003e3.5\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e2\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e1350\u003c/td\u003e\n",
              "      \u003ctd\u003e3.5\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e3\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e2138\u003c/td\u003e\n",
              "      \u003ctd\u003e4.0\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e4\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e2143\u003c/td\u003e\n",
              "      \u003ctd\u003e4.0\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "  \u003c/tbody\u003e\n",
              "\u003c/table\u003e\n",
              "\u003c/div\u003e"
            ],
            "text/plain": [
              "   user_id  movie_id  rating\n",
              "0        1      1217     3.5\n",
              "1        1      1348     3.5\n",
              "2        1      1350     3.5\n",
              "3        1      2138     4.0\n",
              "4        1      2143     4.0"
            ]
          },
          "execution_count": 22,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "df_rating_new \u003d pd.read_csv(\u0027./data/rating_new.csv\u0027)\n",
        "df_rating_new.head()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "pycharm": {}
      },
      "source": [
        "### id变index"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 23,
      "metadata": {
        "pycharm": {}
      },
      "outputs": [
        {
          "data": {
            "text/html": [
              "\u003cdiv\u003e\n",
              "\u003cstyle scoped\u003e\n",
              "    .dataframe tbody tr th:only-of-type {\n",
              "        vertical-align: middle;\n",
              "    }\n",
              "\n",
              "    .dataframe tbody tr th {\n",
              "        vertical-align: top;\n",
              "    }\n",
              "\n",
              "    .dataframe thead th {\n",
              "        text-align: right;\n",
              "    }\n",
              "\u003c/style\u003e\n",
              "\u003ctable border\u003d\"1\" class\u003d\"dataframe\"\u003e\n",
              "  \u003cthead\u003e\n",
              "    \u003ctr style\u003d\"text-align: right;\"\u003e\n",
              "      \u003cth\u003e\u003c/th\u003e\n",
              "      \u003cth\u003euser_id\u003c/th\u003e\n",
              "      \u003cth\u003emovie_index\u003c/th\u003e\n",
              "      \u003cth\u003erating\u003c/th\u003e\n",
              "    \u003c/tr\u003e\n",
              "  \u003c/thead\u003e\n",
              "  \u003ctbody\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e0\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e148\u003c/td\u003e\n",
              "      \u003ctd\u003e3.5\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e1\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e168\u003c/td\u003e\n",
              "      \u003ctd\u003e3.5\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e2\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e169\u003c/td\u003e\n",
              "      \u003ctd\u003e3.5\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e3\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e259\u003c/td\u003e\n",
              "      \u003ctd\u003e4.0\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "    \u003ctr\u003e\n",
              "      \u003cth\u003e4\u003c/th\u003e\n",
              "      \u003ctd\u003e1\u003c/td\u003e\n",
              "      \u003ctd\u003e261\u003c/td\u003e\n",
              "      \u003ctd\u003e4.0\u003c/td\u003e\n",
              "    \u003c/tr\u003e\n",
              "  \u003c/tbody\u003e\n",
              "\u003c/table\u003e\n",
              "\u003c/div\u003e"
            ],
            "text/plain": [
              "   user_id  movie_index  rating\n",
              "0        1          148     3.5\n",
              "1        1          168     3.5\n",
              "2        1          169     3.5\n",
              "3        1          259     4.0\n",
              "4        1          261     4.0"
            ]
          },
          "execution_count": 23,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "df_rating_new[\u0027movie_id\u0027] \u003d df_rating_new[\u0027movie_id\u0027].apply(lambda movie_id : movie_new_id_to_index_dict[movie_id])\n",
        "df_rating_new.columns \u003d [\u0027user_id\u0027,\u0027movie_index\u0027,\u0027rating\u0027]\n",
        "df_rating_new.head()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "pycharm": {}
      },
      "source": [
        "### 得到用户真正喜欢的新物品"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 24,
      "metadata": {
        "pycharm": {}
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "0..100..200..300..400..500..600..700..800..900..1000..1100..1200..1300..1400..1500..1600..1700..1800..1900..2000..2100..2200..2300..2400..2500..2600..2700..2800..2900..3000..3100..3200..3300..3400..3500..3600..3700..3800..3900..4000..4100..4200..4300..4400..4500..4600..4700..4800..4900..5000..5100..5200..5300..5400..5500..5600..5700..5800..5900..6000..6100..6200..6300..6400..6500..6600..6700..6800..6900..7000..7100..7200..7300..7400..7500..7600..7700..7800..7900..8000..8100..8200..8300..8400..8500..8600..8700..8800..8900..9000..9100..9200..9300..9400..9500..9600..9700..9800..9900..10000..10100..10200..10300..10400..10500..10600..10700..10800..10900..11000..11100..11200..11300..11400..11500..11600..11700..11800..11900..12000..12100..12200..12300..12400..12500..12600..12700..12800..12900..13000..13100..13200..13300..13400..13500..13600..13700..13800..13900..14000..14100..14200..14300..14400..14500..14600..14700..14800..14900..15000..15100..15200..15300..15400..15500..15600..15700..15800..15900..16000..16100..16200..16300..16400..16500..16600..16700..16800..16900..17000..17100..17200..17300..17400..17500..17600..17700..17800..17900..18000..18100..18200..18300..18400..18500..18600..18700..18800..18900..19000..19100..19200..19300..19400..19500..19600..19700..19800..19900..20000..20100..20200..20300..20400..20500..20600..20700..20800..20900..21000..21100..21200..21300..21400..21500..21600..21700..21800..21900..22000..22100..22200..22300..22400..22500..22600..22700..22800..22900..23000..23100..23200..23300..23400..23500..23600..23700..23800..23900..24000..24100..24200..24300..24400..24500..24600..24700..24800..24900..25000..25100..25200..25300..25400..25500..25600..25700..25800..25900..26000..26100..26200..26300..26400..26500..26600..26700..26800..26900..27000..27100..27200..27300..27400..27500..27600..27700..27800..27900..28000..28100..28200..28300..28400..28500..28600..28700..28800..28900..29000..29100..29200..29300..29400..29500..29600..29700..29800..29900..30000..30100..30200..30300..30400..30500..30600.."
          ]
        }
      ],
      "source": [
        "user_fav \u003d {}\n",
        "\n",
        "for index,(user_id,groupby_userid) in enumerate(df_rating_new.groupby(\u0027user_id\u0027)):\n",
        "    movies_rating \u003d groupby_userid.groupby(\u0027movie_index\u0027)[\u0027rating\u0027].mean().sort_values(ascending\u003dFalse)\n",
        "    movie_indexs \u003d set(movies_rating[\n",
        "        movies_rating \u003e\u003d 3\n",
        "    ].index.tolist())\n",
        "    user_fav[user_id] \u003d movie_indexs\n",
        "    if index % 100 \u003d\u003d 0:print(index,end\u003d\u0027..\u0027)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "pycharm": {}
      },
      "source": [
        "### 计算准确率和召回率"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 26,
      "metadata": {
        "pycharm": {}
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "准确率 0.0721781590351196\n",
            "召回率 0.16878049831774863\n"
          ]
        }
      ],
      "source": [
        "# 为用户推荐的，用户也喜欢的个数  \n",
        "union_quantity \u003d 0\n",
        "# 为用户推荐的商品总数\n",
        "recommend_quantity \u003d 0\n",
        "# 用户喜欢的商品总数\n",
        "fav_quantity \u003d 0\n",
        "\n",
        "\n",
        "for user_id in user_recommend.keys():\n",
        "    if user_id in user_fav.keys():\n",
        "        union_quantity +\u003d len(\n",
        "            # 通过取交集获得为用户推荐的，用户也喜欢的个数\n",
        "            user_recommend[user_id] \u0026 user_fav[user_id]\n",
        "        )\n",
        "        recommend_quantity +\u003d len(user_recommend[user_id])\n",
        "        fav_quantity +\u003d len(user_fav[user_id])\n",
        "\n",
        "print(\u0027准确率\u0027,union_quantity / recommend_quantity)\n",
        "print(\u0027召回率\u0027,union_quantity / fav_quantity)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "pycharm": {}
      },
      "outputs": [],
      "source": []
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.7.3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 2
}